home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / jaq / dist / jbuild.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-02  |  14.0 KB  |  569 lines

  1. /* 
  2.  * jbuild.c --
  3.  *
  4.  *    Rebuild a Jaquith index from tape.
  5.  *
  6.  * Copyright 1991 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  *
  15.  */
  16.  
  17. #ifndef lint
  18. static char rcsid[] = "$Header: /sprite/lib/forms/RCS/jbuild.c,v 1.0 91/01/07 18:02:37 mottsmth Exp $ SPRITE (Berkeley)";
  19. #endif /* not lint */
  20.  
  21. #include "jaquith.h"
  22. #include "option.h"
  23.  
  24. static char printBuf[T_MAXSTRINGLEN];
  25.  
  26. static FILE *memDbg = NULL;   /* stream for memory tracing */
  27.  
  28. int jDebug;                   /* Internal debugging only */
  29. int syserr = 0;               /* Our personal record of errno */
  30.  
  31. #define DEF_DEVNAME ""
  32. #define DEF_VERBOSE 0
  33. #define DEF_CLOBBER 0
  34. #define DEF_NOINDEX 0
  35. #define DEF_SAVE 0
  36. #define DEF_FIRST 0
  37. #define DEF_LAST -1
  38. #define DEF_MATCHPATH ""
  39. #define DEF_MATCHTBUF ""
  40. #define DEF_BEFORE ""
  41. #define DEF_AFTER ""
  42. #define MAXFILE 100000        /* Completely arbitrary. */
  43.  
  44. static void  CheckOptions   _ARGS_ ((Parms *parmsPtr));
  45. static void  RecoverVolume  _ARGS_ ((char *devName));
  46. static int   RecoverFile    _ARGS_ ((int volStream));
  47. static int   ProcessFile    _ARGS_ ((char *oldName,
  48.                      int *fileCntPtr, int *skipCntPtr));
  49. static int   RebuildIndx    _ARGS_ ((int fileStream, int *fileCntPtr,
  50.                      int *skipCntPtr, char *archPath));
  51. static int   NeedToRestore  _ARGS_ ((T_FileStat *statInfoPtr));
  52.  
  53. typedef struct parmTag {
  54.     char *root;
  55.     char *devName;
  56.     int verbose;
  57.     int clobber;
  58.     int noIndex;
  59.     int save;
  60.     int first;
  61.     int last;
  62.     char *matchPath;
  63.     char *matchTBuf;
  64.     char *before;
  65.     char *after;
  66.     int bufSize;
  67.     time_t beforeDate;        /* converted forms of parms.{before,after} */
  68.     time_t afterDate;
  69. } Parms;
  70.  
  71. Parms parms = {
  72.     DEF_ROOT,
  73.     DEF_DEVNAME,
  74.     DEF_VERBOSE,
  75.     DEF_CLOBBER,
  76.     DEF_NOINDEX,
  77.     DEF_SAVE,
  78.     DEF_FIRST,
  79.     DEF_LAST,
  80.     DEF_MATCHPATH,
  81.     DEF_MATCHTBUF,
  82.     DEF_BEFORE,
  83.     DEF_AFTER,
  84.     T_TARSIZE
  85. };
  86.  
  87. Option optionArray[] = {
  88.     {OPT_STRING, "root", (char *)&parms.root, "Root of index tree"},
  89.     {OPT_STRING, "dev", (char *)&parms.devName, "Device name"},
  90.     {OPT_TRUE, "v", (char *)&parms.verbose, "Verbose mode"},
  91.     {OPT_TRUE, "clobber", (char *)&parms.clobber, "Overwrite old index."},
  92.     {OPT_TRUE, "noindex", (char *)&parms.noIndex, "Restore thdr files but don't rebuild index"},
  93.     {OPT_TRUE, "save", (char *)&parms.save, "Save thdr file after restoration"},
  94.     {OPT_INT, "first", (char *)&parms.first, "First thdr to restore."},
  95.     {OPT_INT, "last", (char *)&parms.last, "Last thdr to restore."},
  96.     {OPT_STRING, "matchpath", (char *)&parms.matchPath, "Restore subtrees whose path name matches globbing expression"},
  97.     {OPT_STRING, "matchtbuf", (char *)&parms.matchTBuf, "Restore files whose tbuf number matches globbing expression"},
  98.     {OPT_STRING, "before", (char *)&parms.before, "Restore files archived prior to date"},
  99.     {OPT_STRING, "after", (char *)&parms.after, "Restore files archived since date"},
  100.     {OPT_INT, "bufsize", (char *)&parms.bufSize, "Unit of tape I/O."}
  101. };
  102. int numOptions = sizeof(optionArray) / sizeof(Option);
  103.  
  104.  
  105. /*
  106.  *----------------------------------------------------------------------
  107.  *
  108.  * jbuild --
  109.  *
  110.  *    Rebuild a Jaquith index from tape.
  111.  *
  112.  * Results:
  113.  *    none.
  114.  *
  115.  * Side effects:
  116.  *    Modifies/creates jaquith disk index structure.
  117.  *
  118.  * Note:
  119.  *      Only handles 1 tape at a time. Should be able to
  120.  *      read filemap list and restore entire index automatically.
  121.  *
  122.  *----------------------------------------------------------------------
  123.  */
  124.  
  125. int
  126. main(argc, argv)
  127.     int argc;                 /* See Option Array */
  128.     char *argv[];
  129. {
  130.     int retCode;
  131.     char *myName;
  132.     uid_t myId;
  133.  
  134. /*    memDbg = fopen("jbuild.mem","w"); */
  135.     MEM_CONTROL(8192, memDbg, TRACEMEM+TRACECALLS, 4096);
  136.  
  137.     argc = Opt_Parse(argc, argv, optionArray, numOptions, 0);
  138.  
  139.     CheckOptions(&parms);
  140.  
  141.     if (access(parms.root, W_OK) == -1) {
  142.     Utils_Bailout("Can't find (or write permission denied): %s", parms.root);
  143.     }
  144.  
  145.     RecoverVolume(parms.devName);
  146.  
  147.     MEM_REPORT("jbuild", ALLROUTINES, SORTBYOWNER);
  148.  
  149.     return T_SUCCESS;
  150. }
  151.  
  152.  
  153.  
  154. /*
  155.  *----------------------------------------------------------------------
  156.  *
  157.  * RecoverVolume -- 
  158.  *
  159.  *      Read and recover indexing info from Jaquith tape.
  160.  *
  161.  * Results:
  162.  *    none.
  163.  *
  164.  * Side effects:
  165.  *    None.
  166.  *
  167.  *----------------------------------------------------------------------
  168.  */
  169.  
  170. static void
  171. RecoverVolume(devName)
  172.     char *devName;            /* device name */
  173. {
  174.     int volStream;
  175.     int retCode;
  176.     int totFiles = 0;
  177.     int totSkip = 0;
  178.     int indxCnt = 0;
  179.     int fileCnt;
  180.     int skipCnt;
  181.     char tmpName[T_MAXPATHLEN];
  182.  
  183.     if ((volStream=Dev_OpenVolume(devName, O_RDONLY)) == -1) {
  184.     sprintf(printBuf, "Open of %s failed", devName);
  185.     Utils_Bailout(printBuf, BAIL_PERROR);
  186.     }
  187.  
  188.     sprintf(tmpName, "%s/rebuild.%x", parms.root, getpid());
  189.  
  190.     if (parms.verbose) {
  191.     fprintf(stdout, "Seeking to file %d\n", parms.first);
  192.     }
  193.     if (Dev_SeekVolume(volStream, parms.first*2, DEV_ABSOLUTE) != T_SUCCESS) {
  194.     sprintf(printBuf, "Couldn't seek to first file. Errno %d", syserr);
  195.     Utils_Bailout(printBuf, BAIL_PERROR);
  196.     }
  197.  
  198.     while ((parms.last == -1) || (fileCnt <= parms.last)) {
  199.     if (RecoverFile(volStream, tmpName) != T_SUCCESS) {
  200.         break;
  201.     }
  202.     if (ProcessFile(tmpName, &fileCnt, &skipCnt) != T_SUCCESS) {
  203.         break;
  204.     }
  205.     if (fileCnt) {
  206.         totFiles += fileCnt;
  207.         totSkip += skipCnt;
  208.         indxCnt++;
  209.     }
  210.     if (Dev_SeekVolume(volStream, 1, DEV_RELATIVE) != T_SUCCESS) {
  211.         break;
  212.     }
  213.     }
  214.  
  215.     unlink(tmpName);
  216.     close(volStream);
  217.  
  218.     fprintf(stdout, "Done. Rebuilt %d index files. Installed %d entries, skipped %d.\n",
  219.         indxCnt, totFiles, totSkip);
  220.  
  221. }
  222.  
  223.  
  224. /*
  225.  *----------------------------------------------------------------------
  226.  *
  227.  * RecoverFile --
  228.  *
  229.  *    Read one indx file.
  230.  *
  231.  * Results:
  232.  *    none.
  233.  *
  234.  * Side effects:
  235.  *    Restore index file from tape.
  236.  *
  237.  *----------------------------------------------------------------------
  238.  */
  239.  
  240. static int
  241. RecoverFile(volStream, oldName)
  242.     int volStream;            /* source volume stream */
  243.     char *oldName;            /* destination file name */
  244. {
  245.     int len;
  246.     static char *buf = NULL;
  247.     int fileStream;
  248.  
  249.     if (buf == NULL) {
  250.     buf = MEM_ALLOC("RecoverFile", parms.bufSize);
  251.     }
  252.  
  253.     if ((fileStream=open(oldName, O_WRONLY+O_CREAT, 0660)) == -1) {
  254.     sprintf(printBuf, "Open of %s failed", oldName);
  255.     Utils_Bailout(printBuf, BAIL_PERROR);
  256.     }
  257.  
  258.     while ((len=Dev_ReadVolume(volStream, buf, parms.bufSize)) > 0) {
  259.     if (write(fileStream, buf, len) != len) {
  260.         sprintf(printBuf,"Short write. errno %d\n", syserr);
  261.         return T_FAILURE;
  262.     }
  263.     if (len < sizeof(buf)) {
  264.         break;
  265.     }
  266.     }
  267.  
  268.     close(fileStream);
  269.  
  270.     if (len < 0) {
  271.     return T_FAILURE;
  272.     } else {
  273.     return T_SUCCESS;
  274.     }
  275.  
  276. }
  277.  
  278.  
  279. /*
  280.  *----------------------------------------------------------------------
  281.  *
  282.  * ProcessFile --
  283.  *
  284.  *    Process the restored index file.
  285.  *
  286.  * Results:
  287.  *    none.
  288.  *
  289.  * Side effects:
  290.  *    Overwrites old index info according to parms flags.
  291.  *
  292.  *----------------------------------------------------------------------
  293.  */
  294.  
  295. static int
  296. ProcessFile(oldName, fileCntPtr, skipCntPtr)
  297.     char *oldName;            /* source filename */
  298.     int *fileCntPtr;          /* receiving restoration count */
  299.     int *skipCntPtr;          /* receiving skip count */
  300. {
  301.     FILE *fileStream;
  302.     char tarHdr[T_TBLOCK];
  303.     char newName[T_MAXPATHLEN];
  304.     T_FileStat statInfo;
  305.     static int unknownCnt = 0;
  306.     char archPath[T_MAXPATHLEN];
  307.     int retCode = T_SUCCESS;
  308.     int fileCnt;
  309.     int skipCnt;
  310.  
  311.     if ((fileStream=fopen(oldName, "r")) == (FILE *)NULL) {
  312.     fprintf(stderr,    "Couldn't open %s. Errno %d\n", oldName, errno);
  313.     return -1;
  314.     }
  315.  
  316.     if (fread(tarHdr, sizeof(tarHdr), 1, fileStream) != 1) {
  317.     retCode = T_FAILURE;
  318.     fprintf(stderr,    "Couldn't read tar block.\n");
  319.     } else if (TBuf_ParseTarHdr(tarHdr, &statInfo) != T_SUCCESS) {
  320.     retCode = T_FAILURE;
  321.     fprintf(stderr,    "Couldn't parse tar block.\n");
  322.     } else if (*statInfo.fileName == '/') {
  323.     retCode = T_FAILURE;
  324.     fprintf(stderr,    "Unexpected thdr filename: %s.\n", statInfo.fileName);
  325.     }
  326.     
  327.     if (retCode != T_SUCCESS) {
  328.     sprintf(newName, "%s/thdr.%d.%d", parms.root, getpid(), unknownCnt++);
  329.     if (rename(oldName, newName) < 0) {
  330.         fprintf(stdout,"Couldn't rename %s to %s. Errno %d\n",
  331.             oldName, newName, errno);
  332.     } else {
  333.         fprintf(stdout,"Preserved file as %s.\n", newName);
  334.     }
  335.     } else {
  336.     strcpy(newName, parms.root);
  337.     strcat(newName, "/");
  338.     strcat(newName, statInfo.fileName);
  339.     if (access(newName, F_OK) != -1) {
  340.         if (!parms.clobber) {
  341.         sprintf(printBuf, "File '%s' exists. Overwrite it? [y/n] ",
  342.             newName);
  343.         if (!Utils_GetOk(printBuf)) {
  344.             fclose(fileStream);
  345.             return T_SUCCESS;
  346.         }
  347.         }
  348.         if (unlink(newName) == -1) {
  349.         fprintf(stdout,"Couldn't remove %s. Errno %d\n",
  350.             newName, errno);
  351.         }
  352.     }
  353.     if (rename(oldName, newName) < 0) {
  354.         fprintf(stdout,"Couldn't rename %s to %s. Errno %d\n",
  355.             oldName, newName, errno);
  356.     } else {
  357.         if (parms.verbose) {
  358.         fprintf(stdout,"Restored %s.\n", newName);
  359.         }
  360.         if (!parms.noIndex) {
  361.             strcpy(archPath, newName);
  362.         *(STRRCHR(archPath, '/')) = '\0';
  363.         if ((RebuildIndx(fileStream, &fileCnt, &skipCnt, archPath)
  364.              == T_SUCCESS) && (!parms.save)) {
  365.             unlink(newName);
  366.         }
  367.         if (parms.verbose) {
  368.             fprintf(stdout,"Installed %d entries, skipped %d.\n",
  369.                 fileCnt, skipCnt);
  370.         }
  371.         }
  372.     }
  373.     }
  374.  
  375.     fclose(fileStream);
  376.  
  377.     *fileCntPtr = fileCnt;
  378.     *skipCntPtr = skipCnt;
  379.  
  380.     return T_SUCCESS;
  381. }
  382.  
  383.  
  384. /*
  385.  *----------------------------------------------------------------------
  386.  *
  387.  * RebuildIndx --
  388.  *
  389.  *    Read through file, extracting and rebuilding entries.
  390.  *
  391.  * Results:
  392.  *    none.
  393.  *
  394.  * Side effects:
  395.  *    None.
  396.  *
  397.  *----------------------------------------------------------------------
  398.  */
  399.  
  400. static int
  401. RebuildIndx(fileStream, fileCntPtr, skipCntPtr, archPath)
  402.     int fileStream;           /* source fileStream */    
  403.     int *fileCntPtr;          /* resulting file count */    
  404.     int *skipCntPtr;          /* resulting skip count */    
  405.     char *archPath;           /* owning archive */
  406. {
  407.     int retCode = T_SUCCESS;
  408.     T_FileStat statInfo;
  409.     char indxPath[T_MAXPATHLEN*2];
  410.     char newIndxPath[T_MAXPATHLEN*2];
  411.     FILE *indxStream = NULL;
  412.     int fileCnt = 0;
  413.     int skipCnt = 0;
  414.  
  415.     *fileCntPtr = 0;
  416.     *indxPath = '\0';
  417.  
  418.     while (Indx_ReadIndxEntry(fileStream, &statInfo) == T_SUCCESS) {
  419.  
  420.     /* Need to restore this thing ? */
  421.         if (!NeedToRestore(&statInfo)) {
  422.         skipCnt++;
  423.         continue;
  424.     }
  425.  
  426.     /* find out what indx file file belongs to */
  427.     Indx_MakeIndx(archPath, statInfo.fileName, newIndxPath);
  428.  
  429.     /* Open indx file, if necessary */
  430.     if (strcmp(newIndxPath, indxPath) != 0) {
  431.         if (indxStream != NULL) {
  432.         Indx_Close(indxStream);
  433.         }
  434.         if (Indx_Open(newIndxPath, "a", &indxStream) != T_SUCCESS) {
  435.         sprintf(printBuf, "Open of %s failed. Errno %d",
  436.             indxPath, syserr);
  437.         Utils_Bailout(printBuf, BAIL_PRINT);
  438.         }
  439.         strcpy(indxPath, newIndxPath);
  440.     }
  441.  
  442.     if (Indx_WriteIndxEntry(&statInfo, -1, indxStream) < 0) {
  443.         sprintf(printBuf, "Write of %s failed. Errno %d",
  444.             indxPath, syserr);
  445.         Utils_Bailout(printBuf, BAIL_PRINT);
  446.     }
  447.     fileCnt++;
  448.     }
  449.  
  450.     if (indxStream != NULL) {
  451.     Indx_Close(indxStream);
  452.     }
  453.  
  454.     *fileCntPtr = fileCnt;
  455.     *skipCntPtr = skipCnt;
  456.  
  457.     return retCode;
  458. }
  459.  
  460.  
  461. /*
  462.  *----------------------------------------------------------------------
  463.  *
  464.  * NeedToRestore -- 
  465.  *
  466.  *    Determine whether this entry should be restored or not
  467.  *
  468.  * Results:
  469.  *    1 == need to restore; 0 == skip it
  470.  *
  471.  * Side effects:
  472.  *    none.
  473.  *
  474.  *----------------------------------------------------------------------
  475.  */
  476.  
  477. static int
  478. NeedToRestore(statInfoPtr)
  479.     T_FileStat *statInfoPtr;
  480. {
  481.     char buf[20];
  482.  
  483.     if ((*parms.matchPath) &&
  484.     (!Str_Match(statInfoPtr->fileName, parms.matchPath))) {
  485.     return 0;
  486.     }
  487.  
  488.     if (*parms.matchTBuf) {
  489.     sprintf(buf, "%d", statInfoPtr->tBufId);
  490.     if (!Str_Match(buf, parms.matchTBuf)) {
  491.         return 0;
  492.     }
  493.     }
  494.  
  495.     if ((*parms.before) &&
  496.     (Time_Compare(statInfoPtr->vtime, parms.beforeDate, 0) > 0)) {
  497.     return 0;
  498.     }
  499.  
  500.     if ((*parms.after) &&
  501.     (Time_Compare(statInfoPtr->vtime, parms.afterDate, 02) < 0)) {
  502.     return 0;
  503.     }
  504.  
  505.     return 1;
  506. }
  507.  
  508.  
  509.  
  510. /*
  511.  *----------------------------------------------------------------------
  512.  *
  513.  * CheckOptions -- 
  514.  *
  515.  *    Make sure command line options look reasonable
  516.  *
  517.  * Results:
  518.  *    none.
  519.  *
  520.  * Side effects:
  521.  *    none.
  522.  *
  523.  *----------------------------------------------------------------------
  524.  */
  525.  
  526. static void
  527. CheckOptions(parmsPtr)
  528.     Parms *parmsPtr;          /* command line args */
  529. {
  530.     char devName[T_MAXLINELEN];
  531.     struct timeb timeB1;
  532.  
  533.     if (!*parmsPtr->devName) {
  534.     fprintf(stderr,"Name of reader device? ");
  535.     gets(devName);
  536.     parmsPtr->devName = Str_Dup(devName);
  537.     }
  538.     if ((parmsPtr->first < 0) || (parmsPtr->first > MAXFILE)) {
  539.     Utils_Bailout("Bad -first argument.", BAIL_PRINT);
  540.     }
  541.     if ((parmsPtr->last < -1) || (parmsPtr->last > MAXFILE)) {
  542.     Utils_Bailout("Bad -last argument.", BAIL_PRINT);
  543.     }
  544.     if (*parmsPtr->before) {
  545.     if (getindate(parmsPtr->before, &timeB1) != T_SUCCESS) {
  546.         Utils_Bailout("Need date in format: 20-Mar-1980:10:20:0",
  547.               BAIL_PRINT);
  548.     }
  549.     parmsPtr->beforeDate = timeB1.time;
  550.     }
  551.     if (*parmsPtr->after) {
  552.     if (getindate(parmsPtr->after, &timeB1) != T_SUCCESS) {
  553.         Utils_Bailout("Need date in format: 20-Mar-1980:10:20:0",
  554.               BAIL_PRINT);
  555.     }
  556.     parmsPtr->afterDate = timeB1.time;
  557.     }
  558.     if ((*parmsPtr->before) && (*parmsPtr->after) &&
  559.     (Time_Compare(parmsPtr->beforeDate, parmsPtr->afterDate, 0) > 0)) {
  560.     Utils_Bailout("Contradictory -before and -after options.", BAIL_PRINT);
  561.     }
  562.     if ((parmsPtr->bufSize <= 0) && (parmsPtr->bufSize % T_TAPEUNIT)){
  563.     sprintf(printBuf, "Need buffer size > 0 and a multiple of %d.\n",
  564.         T_TAPEUNIT);
  565.     Utils_Bailout(printBuf, BAIL_PRINT);
  566.     }
  567.  
  568. }
  569.